//
//  MacroFunctions.h
//  FeinnoShareLibrary
//
//  Created by Michael.Tan on 12-8-31.
//  Copyright (c) 2012年 Feinno. All rights reserved.
//

// MARK: - Block Helper
#if NS_BLOCKS_AVAILABLE

#define KNSAFE_BLOCK_CALL_NO_P(b) (b == nil ?: b())
#define KNSAFE_BLOCK_CALL(b, p) (b == nil ? : b(p) )
#define KNSAFE_BLOCK_CALL_2_P(b, p1, p2) (b == nil ? : b(p1, p2))

#endif

#define KNRelativeWidthBase3x(target3x) ceil((CGFloat)target3x/414 * KNSCREENWIDTH)

#define KNRelativeHeightBase3x(target3x) ceil((CGFloat)target3x/736 * KNSCREENHEIGHT)


#ifdef DEBUG
#define KNDLog( s, ... ) NSLog( @"<%@:(%d)> %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define KNDLog( s, ... )
#endif

/*
 *  System Versioning Preprocessor Macros
 */

#define KNSYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define KNSYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define KNSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define KNSYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define KNSYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

#define KNStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height

#define KNNavBarHeight 44.0

#define KNTopHeight (KNStatusBarHeight + KNNavBarHeight)
#define KNRandomColor random(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256))

//字符串
#define KN_Trim(x) [x stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]
#define KN_SWF(FORMAT, ...) [NSString stringWithFormat:FORMAT, __VA_ARGS__]
#define KN_Replace(raw,f,r) [raw stringByReplacingOccurrencesOfString:f withString:r]

//颜色
#define KN_ColorFromRGB(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0]
#define KN_ColorFromRGBA(r,g,b,a) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a]
#define KN_ColorFromRGBA2(rgbValue, alphaValue) \
[UIColor \
colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \
blue:((float)(rgbValue & 0x0000FF))/255.0 \
alpha:alphaValue]

#define KNW(obj)   (!obj?0:(obj).frame.size.width)
#define KNH(obj)   (!obj?0:(obj).frame.size.height)
#define KNFont(x) [UIFont systemFontOfSize:x]
#define KNBFont(x) [UIFont boldSystemFontOfSize:x]


#define KNRGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0f green:(g)/255.0f blue:(b)/255.0f alpha:1]
#define KNRGBACOLOR(r,g,b,a) [UIColor colorWithRed:(r)/255.0f green:(g)/255.0f blue:(b)/255.0f alpha:(a)]

#define KNSCREENWIDTH ([UIScreen mainScreen].bounds.size.width)
#define KNSCREENHEIGHT ([UIScreen mainScreen].bounds.size.height)


//通知处理
#define KNAddN(_selector,_name)\
([[NSNotificationCenter defaultCenter] addObserver:self selector:_selector name:_name object:nil])

#define KNRemoveNObserverWithName(_name)\
([[NSNotificationCenter defaultCenter] removeObserver:self name:_name object:nil])

#define KNRemoveNObserver() ([[NSNotificationCenter defaultCenter] removeObserver:self])

#define KNPostN(_name)\
([[NSNotificationCenter defaultCenter] postNotificationName:_name object:nil userInfo:nil])

#define KNPostNWithObj(_name,_obj)\
([[NSNotificationCenter defaultCenter] postNotificationName:_name object:_obj userInfo:nil])

#define KNPostNWithInfos(_name,_obj,_infos)\
([[NSNotificationCenter defaultCenter] postNotificationName:_name object:_obj userInfo:_infos])

// MARK: - String Helper
#define KNNULL_STR(str, default) (str ?: default)
#define KNEMPTY_STR(str, default) (str ? (str.length == 0 ? default : str ) : default)
#define KNNULL_STR_DEFAULT_TO_EMPTY(str) NULL_STR(str, @"")
#define KNNULL_ARRAY_DEFAULT_TO_EMPTY(o, default) (o ?: default)

/**
 * 通知中心
 */
#define KNNOTIFICATION [NSNotificationCenter defaultCenter]

/**
 * 屏幕尺寸
 */
#define KNSCREEN_BOUNDS [[UIScreen mainScreen] bounds]

// 文件
#define KNPATH_DOCUMENT    [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]

#define KNSET_DEFAULT(_obj_,_key_) [[NSUserDefaults standardUserDefaults] setObject:_obj_ forKey:_key_]
#define KNSYNC_DEFAULT [[NSUserDefaults standardUserDefaults] synchronize]
#define KNGET_DEFOULT(_key_) [[NSUserDefaults standardUserDefaults] objectForKey:_key_]


#pragma mark - Syetem

#pragma mark - System class or path
/**KEYWINDOW对象*/
#define KNKEY_WINDOW                      [[UIApplication sharedApplication] keyWindow]
/**AppDelegate对象*/
#define KNAPPDELEGATE_INSTANCE            ((AppDelegate *)[[UIApplication sharedApplication] delegate])

/**App主目录   可见子目录(3个):Documents、Library、tmp*/
#define KNAPP_PATH NSHomeDirectory()
/**Documents路径   文档目录(ITUNES要同步)*/
#define KNAPP_DOCUMENTS_PATH              [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
/**Library路径   资源目录*/
#define KNAPP_LIBRARY_PATH                [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject]
/**Library/Caches   资源缓存(ITUNES不同步)*/
#define KNAPP_LIBRARY_CACHES_PATH         [APP_LIBRARY_PATH stringByAppendingPathComponent:@"/Caches"]
/**Library/Preferences  配置目录(ITUNES要同步)*/
#define KNAPP_LIBRARY_PREFERENCES_PATH    [APP_LIBRARY_PATH stringByAppendingPathComponent:@"/Preferences"]
/**tmp目录   缓存目录(ITUNES不同步,程序退出后自动清空)*/
#define KNAPP_TMP_PATH                    [NSHomeDirectory() stringByAppendingFormat:@"/tmp"]

#pragma mark - SetValue
\
/**得到字符串的像素矩阵*/
#define KNSTRING_WITH_SIZE_AND_DEFAULT_HEIGHT(string, font, width) iOS7_AND_LATER ? [string boundingRectWithSize:CGSizeMake(width, NSIntegerMax) options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil].size : [string sizeWithFont:font constrainedToSize:CGSizeMake(width, NSIntegerMax)]

#define KNSTRING_WITH_SIZE(string, font, width, height) [string boundingRectWithSize:CGSizeMake(width, height) options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil].size

/**加载nib文件*/
#define KNLOAD_NIB(_NibName_) [[NSBundle mainBundle] loadNibNamed:_NibName_ owner:nil options:nil][0]
/**获取MAINBUNDLE*/
#define KNMAIN_BUNDLE                                    [NSBundle mainBundle]
/**获取bundle文件路径*/
#define KNBANDLE_FILE_PATH(filename,extension)           [KNMAIN_BUNDLE pathForResource:filename ofType:extension]
/**加载图片  内存*/
#define KNLOAD_IMAGE(filename)                           [UIImage imageNamed:filename]
/**加载图片  从文件加载*/
#define KNLOAD_IMAGE_WITH_FILE_PATH(path)                [UIImage imageWithContentsOfFile:path]

#pragma mark - Assist

/**主线程执行block*/
#define KNPerfromBlockWithMainQueue(coding)    dispatch_async(dispatch_get_main_queue(), ^{ coding; });

/**弹出AlterView*/
#define KNALERT(msg)                                   [[[UIAlertView alloc]initWithTitle:@"系统提示" message:msg delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil] show]

#define KNWEAK_SELF                                     __weak typeof(self) wself = self;
#define KNWEAK(obj)                                     __weak typeof(obj) wobj = obj;

#define KNFORMAT_STR(_str_) [NSString stringWithFormat:@"%@",_str_]

//G－C－D
#define KNBACK(block) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block)
#define KNMAIN(block) dispatch_async(dispatch_get_main_queue(),block)
#define KNAFTER(block,s) dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(s * NSEC_PER_SEC)), dispatch_get_main_queue(), block)

#define KNDegreesToRadians(x) (M_PI*(x)/180.0) //把角度转换成PI的方式
#define KNRadiansToDegrees(radians) ((radians) * (180.0 / M_PI))

#define KNSINGLE_LINE_WIDTH           (1.0f / [UIScreen mainScreen].scale)
#define KNSCREEN_SCALE [UIScreen mainScreen].scale

// notificaitoon
#define KNPostNotification(name,obj) [[NSNotificationCenter defaultCenter] postNotificationName:name object:obj]

#define KNAddNotification(id,s,n,o)              [[NSNotificationCenter defaultCenter] addObserver:id selector:s name:n object:o]
#define KNRemoveNotification(id,n,o)             [[NSNotificationCenter defaultCenter] removeObserver:id name:n object:o]
#define KNRemoveNotifications                     [[NSNotificationCenter defaultCenter] removeObserver:self]

#define KNADAPTER_SIZE(n) (n * [UIScreen mainScreen].bounds.size.width / 320.0f)

#define KNIS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 8.0)

#define KNiPhone5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), [[UIScreen mainScreen] currentMode].size) : NO)

#define KNAPP_VERSION                             [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]

#define KNSafeSetObject(obj,key,value) if (value) [obj setObject:value forKey:key]

#define KNGetVCWithSB(sbName,vcName) [[UIStoryboard storyboardWithName:sbName bundle:nil] instantiateViewControllerWithIdentifier:vcName]

#define kStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height

#define kNavBarHeight 44.0

#define kTopHeight (kStatusBarHeight + kNavBarHeight)


#define kiPhoneX [KNHelper KNIsIphoneFullScreen]
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif

#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif
